home *** CD-ROM | disk | FTP | other *** search
/ Clickx 96 / Clickx 96.iso / software / tools / tool / xbmc-10.1.exe / addons / script.module.pil / lib / PIL / PdfImagePlugin.py < prev    next >
Encoding:
Python Source  |  2009-04-06  |  5.4 KB  |  212 lines

  1. #
  2. # The Python Imaging Library.
  3. # $Id$
  4. #
  5. # PDF (Acrobat) file handling
  6. #
  7. # History:
  8. # 1996-07-16 fl   Created
  9. # 1997-01-18 fl   Fixed header
  10. # 2004-02-21 fl   Fixes for 1/L/CMYK images, etc.
  11. # 2004-02-24 fl   Fixes for 1 and P images.
  12. #
  13. # Copyright (c) 1997-2004 by Secret Labs AB.  All rights reserved.
  14. # Copyright (c) 1996-1997 by Fredrik Lundh.
  15. #
  16. # See the README file for information on usage and redistribution.
  17. #
  18.  
  19. ##
  20. # Image plugin for PDF images (output only).
  21. ##
  22.  
  23. __version__ = "0.4"
  24.  
  25. import Image, ImageFile
  26. import StringIO
  27.  
  28.  
  29. #
  30. # --------------------------------------------------------------------
  31.  
  32. # object ids:
  33. #  1. catalogue
  34. #  2. pages
  35. #  3. image
  36. #  4. page
  37. #  5. page contents
  38.  
  39. def _obj(fp, obj, **dict):
  40.     fp.write("%d 0 obj\n" % obj)
  41.     if dict:
  42.         fp.write("<<\n")
  43.         for k, v in dict.items():
  44.             if v is not None:
  45.                 fp.write("/%s %s\n" % (k, v))
  46.         fp.write(">>\n")
  47.  
  48. def _endobj(fp):
  49.     fp.write("endobj\n")
  50.  
  51. ##
  52. # (Internal) Image save plugin for the PDF format.
  53.  
  54. def _save(im, fp, filename):
  55.     resolution = im.encoderinfo.get("resolution", 72.0)
  56.  
  57.     #
  58.     # make sure image data is available
  59.     im.load()
  60.  
  61.     xref = [0]*(5+1) # placeholders
  62.  
  63.     fp.write("%PDF-1.2\n")
  64.     fp.write("% created by PIL PDF driver " + __version__ + "\n")
  65.  
  66.     #
  67.     # Get image characteristics
  68.  
  69.     width, height = im.size
  70.  
  71.     # FIXME: Should replace ASCIIHexDecode with RunLengthDecode (packbits)
  72.     # or LZWDecode (tiff/lzw compression).  Note that PDF 1.2 also supports
  73.     # Flatedecode (zip compression).
  74.  
  75.     bits = 8
  76.     params = None
  77.  
  78.     if im.mode == "1":
  79.         filter = "/ASCIIHexDecode"
  80.         colorspace = "/DeviceGray"
  81.         procset = "/ImageB" # grayscale
  82.         bits = 1
  83.     elif im.mode == "L":
  84.         filter = "/DCTDecode"
  85.         # params = "<< /Predictor 15 /Columns %d >>" % (width-2)
  86.         colorspace = "/DeviceGray"
  87.         procset = "/ImageB" # grayscale
  88.     elif im.mode == "P":
  89.         filter = "/ASCIIHexDecode"
  90.         colorspace = "[ /Indexed /DeviceRGB 255 <"
  91.         palette = im.im.getpalette("RGB")
  92.         for i in range(256):
  93.             r = ord(palette[i*3])
  94.             g = ord(palette[i*3+1])
  95.             b = ord(palette[i*3+2])
  96.             colorspace = colorspace + "%02x%02x%02x " % (r, g, b)
  97.         colorspace = colorspace + "> ]"
  98.         procset = "/ImageI" # indexed color
  99.     elif im.mode == "RGB":
  100.         filter = "/DCTDecode"
  101.         colorspace = "/DeviceRGB"
  102.         procset = "/ImageC" # color images
  103.     elif im.mode == "CMYK":
  104.         filter = "/DCTDecode"
  105.         colorspace = "/DeviceCMYK"
  106.         procset = "/ImageC" # color images
  107.     else:
  108.         raise ValueError("cannot save mode %s" % im.mode)
  109.  
  110.     #
  111.     # catalogue
  112.  
  113.     xref[1] = fp.tell()
  114.     _obj(fp, 1, Type = "/Catalog",
  115.                 Pages = "2 0 R")
  116.     _endobj(fp)
  117.  
  118.     #
  119.     # pages
  120.  
  121.     xref[2] = fp.tell()
  122.     _obj(fp, 2, Type = "/Pages",
  123.                 Count = 1,
  124.                 Kids = "[4 0 R]")
  125.     _endobj(fp)
  126.  
  127.     #
  128.     # image
  129.  
  130.     op = StringIO.StringIO()
  131.  
  132.     if filter == "/ASCIIHexDecode":
  133.         if bits == 1:
  134.             # FIXME: the hex encoder doesn't support packed 1-bit
  135.             # images; do things the hard way...
  136.             data = im.tostring("raw", "1")
  137.             im = Image.new("L", (len(data), 1), None)
  138.             im.putdata(data)
  139.         ImageFile._save(im, op, [("hex", (0,0)+im.size, 0, im.mode)])
  140.     elif filter == "/DCTDecode":
  141.         ImageFile._save(im, op, [("jpeg", (0,0)+im.size, 0, im.mode)])
  142.     elif filter == "/FlateDecode":
  143.         ImageFile._save(im, op, [("zip", (0,0)+im.size, 0, im.mode)])
  144.     elif filter == "/RunLengthDecode":
  145.         ImageFile._save(im, op, [("packbits", (0,0)+im.size, 0, im.mode)])
  146.     else:
  147.         raise ValueError("unsupported PDF filter (%s)" % filter)
  148.  
  149.     xref[3] = fp.tell()
  150.     _obj(fp, 3, Type = "/XObject",
  151.                 Subtype = "/Image",
  152.                 Width = width, # * 72.0 / resolution,
  153.                 Height = height, # * 72.0 / resolution,
  154.                 Length = len(op.getvalue()),
  155.                 Filter = filter,
  156.                 BitsPerComponent = bits,
  157.                 DecodeParams = params,
  158.                 ColorSpace = colorspace)
  159.  
  160.     fp.write("stream\n")
  161.     fp.write(op.getvalue())
  162.     fp.write("\nendstream\n")
  163.  
  164.     _endobj(fp)
  165.  
  166.     #
  167.     # page
  168.  
  169.     xref[4] = fp.tell()
  170.     _obj(fp, 4)
  171.     fp.write("<<\n/Type /Page\n/Parent 2 0 R\n"\
  172.              "/Resources <<\n/ProcSet [ /PDF %s ]\n"\
  173.              "/XObject << /image 3 0 R >>\n>>\n"\
  174.              "/MediaBox [ 0 0 %d %d ]\n/Contents 5 0 R\n>>\n" %\
  175.              (procset, int(width * 72.0 /resolution) , int(height * 72.0 / resolution)))
  176.     _endobj(fp)
  177.  
  178.     #
  179.     # page contents
  180.  
  181.     op = StringIO.StringIO()
  182.  
  183.     op.write("q %d 0 0 %d 0 0 cm /image Do Q\n" % (int(width * 72.0 / resolution), int(height * 72.0 / resolution)))
  184.  
  185.     xref[5] = fp.tell()
  186.     _obj(fp, 5, Length = len(op.getvalue()))
  187.  
  188.     fp.write("stream\n")
  189.     fp.write(op.getvalue())
  190.     fp.write("\nendstream\n")
  191.  
  192.     _endobj(fp)
  193.  
  194.     #
  195.     # trailer
  196.     startxref = fp.tell()
  197.     fp.write("xref\n0 %d\n0000000000 65535 f \n" % len(xref))
  198.     for x in xref[1:]:
  199.         fp.write("%010d 00000 n \n" % x)
  200.     fp.write("trailer\n<<\n/Size %d\n/Root 1 0 R\n>>\n" % len(xref))
  201.     fp.write("startxref\n%d\n%%%%EOF\n" % startxref)
  202.     fp.flush()
  203.  
  204. #
  205. # --------------------------------------------------------------------
  206.  
  207. Image.register_save("PDF", _save)
  208.  
  209. Image.register_extension("PDF", ".pdf")
  210.  
  211. Image.register_mime("PDF", "application/pdf")
  212.